package org.notabug.lifeuser.moviedb;

import android.Manifest;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.ActionBar;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuInflater;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.EditorInfo;
import android.view.KeyEvent;
import android.widget.Toast;
import android.widget.EditText;
import android.widget.TextView;
import android.text.TextWatcher;
import android.text.Editable;
import android.net.Uri;

import java.util.Locale;

/*
* This class will be the parent for all other activities,
* this class will thus include the basics which consists mostly of options_menu items
*
* This class also consists of searching logic although did is not used in all activities.
* This is purely for simplicities' sake and might be improved in the future.
*
* nnuuneoi's article was a great help by programming the permissions for API 23 and higher.
* Article: https://inthecheesefactory.com/blog/things-you-need-to-know-about-android-m-permission-developer-edition
*/
public class BaseActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {

	// Variables used for searching
	protected MenuItem mSearchAction;
	protected boolean isSearchOpened = false;
	protected EditText editSearch;

	final private int REQUEST_CODE_ASK_PERMISSIONS_EXPORT = 123;
	final private int REQUEST_CODE_ASK_PERMISSIONS_IMPORT = 124;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
	}

    protected void setNavigationDrawer() {
        // Create the toolbar
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        // Create the navigation drawer
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open,
                R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        // Set the item listener on the navigation view
        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
    }

	/**
	* ONLY USE THIS ON THE END OF AN URL.
	*/
	protected String getLanguageParameter() {
		if(!Locale.getDefault().getLanguage().equals("en")) {
			return "&language=" + Locale.getDefault().getLanguage();
		}
		return "";
	}

	@Override
	public void onBackPressed() {
		// If the navigation drawer is open, close it
		DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
		if(drawer.isDrawerOpen(GravityCompat.START)) {
			drawer.closeDrawer(GravityCompat.START);
		} else {
			// When search is opened and the user presses back,
			// execute a custom action (removing search query or stop searching)
			if(isSearchOpened) {
				handleMenuSearch();
				return;
			} 
			super.onBackPressed();
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the options_menu; this adds items to the action bar if it is present.
		// Not needed, try to remove it as soon as we have something launchable
		String className = getLocalClassName();

		// The search option is only available for the MovieActivity and ListActivity classes.
		if(className.equals("MovieActivity") || className.equals("ListActivity")) {
			MenuInflater inflater = getMenuInflater();
			inflater.inflate(R.menu.options_menu, menu);
		}

		if(className.equals("ListActivity")) {
			MenuInflater inflater = getMenuInflater();
			inflater.inflate(R.menu.database_menu, menu);
		}
		return true;
	}
	
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

		// Search action
        if (id == R.id.action_search) {
			handleMenuSearch();
            return true;
        }

		// Export action
		if (id == R.id.action_export) {
			if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
				int hasWriteExternalStoragePermission = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
				if(hasWriteExternalStoragePermission != PackageManager.PERMISSION_GRANTED) {
					if(!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
						final Activity activity = this;
						showMessageOKCancel(getApplicationContext().getResources().getString(R.string.no_permission_dialog_message),
								new DialogInterface.OnClickListener() {
									@Override
									public void onClick(DialogInterface dialog, int which) {
										ActivityCompat.requestPermissions(activity, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE},
												REQUEST_CODE_ASK_PERMISSIONS_EXPORT);
									}
								});
						return true;
					}
					ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
							REQUEST_CODE_ASK_PERMISSIONS_EXPORT);

					return true;
				}
			}
			MovieDatabaseHelper databaseHelper = new MovieDatabaseHelper(getApplicationContext());
			databaseHelper.exportDatabase(getApplicationContext());
			return true;

		}

		// Import action
		if (id == R.id.action_import) {
			if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
				int hasWriteExternalStoragePermission = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
				if(hasWriteExternalStoragePermission != PackageManager.PERMISSION_GRANTED) {
					if(!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
						final Activity activity = this;
						showMessageOKCancel(getApplicationContext().getResources().getString(R.string.no_permission_dialog_message),
								new DialogInterface.OnClickListener() {
									@Override
									public void onClick(DialogInterface dialog, int which) {
										ActivityCompat.requestPermissions(activity, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE},
												REQUEST_CODE_ASK_PERMISSIONS_IMPORT);
									}
								});
						return true;
					}
					ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
							REQUEST_CODE_ASK_PERMISSIONS_IMPORT);

					return true;
				}
			}
			MovieDatabaseHelper databaseHelper = new MovieDatabaseHelper(getApplicationContext());
			databaseHelper.importDatabase(this);
			return true;
		}

        return super.onOptionsItemSelected(item);
    }

	private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
		new AlertDialog.Builder(this)
			.setMessage(message)
			.setPositiveButton(getApplicationContext().getResources().getString(R.string.no_permission_dialog_ok), okListener)
			.setNegativeButton(getApplicationContext().getResources().getString(R.string.no_permission_dialog_cancel), null)
			.create()
			.show();
	}

	@Override
	public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
		switch(requestCode) {
			case REQUEST_CODE_ASK_PERMISSIONS_EXPORT:
				if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
					// Permission Granted
					MovieDatabaseHelper databaseHelper = new MovieDatabaseHelper(getApplicationContext());
					databaseHelper.exportDatabase(getApplicationContext());
				} else {
					// Permission Denied
				}
				break;
			case REQUEST_CODE_ASK_PERMISSIONS_IMPORT:
				if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
					// Permission Granted
					MovieDatabaseHelper databaseHelper = new MovieDatabaseHelper(getApplicationContext());
					databaseHelper.importDatabase(getApplicationContext());
				} else {
					// Permission Denied
				}
				break;
			default:
				super.onRequestPermissionsResult(requestCode, permissions, grantResults);
		}
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
		// Do stuff
	}
	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		mSearchAction = menu.findItem(R.id.action_search);
		return super.onPrepareOptionsMenu(menu);
	}
		
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        switch(id) {
			case R.id.nav_popular:
				Intent mIntent = new Intent(getApplicationContext(), MovieActivity.class);
				mIntent.putExtra("movies", "movie");
				startActivity(mIntent);
				break;
			case R.id.nav_series:
				Intent sIntent = new Intent(getApplicationContext(), MovieActivity.class);
				sIntent.putExtra("movies", "tv");
				startActivity(sIntent);
				break;
			case R.id.nav_watched:
				Intent wIntent = new Intent(getApplicationContext(), ListActivity.class);
				wIntent.putExtra("watched", 1);
				startActivity(wIntent);
				break;
			case R.id.nav_to_watch:
				Intent tIntent = new Intent(getApplicationContext(), ListActivity.class);
				tIntent.putExtra("watched", 0);
				startActivity(tIntent);
				break;
			case R.id.nav_source_code:
				Intent browserIntent = new Intent(Intent.ACTION_VIEW,
						Uri.parse("https://www.notabug.org/lifeuser/moviedb"));
				startActivity(browserIntent);
				break;
		}

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

	protected void handleMenuSearch() {
		// Searching will be done in the actionbar.
		ActionBar action = getSupportActionBar();

		// Although the icon changes, the calls are the same,
		// that's why there is a if-statement, to differ
		// requests to start a search from requests to end a search.
		if(isSearchOpened) {
			// Close the search or delete the search query.
			if(editSearch.getText().toString().equals("")) {
				action.setDisplayShowCustomEnabled(true);

				// Change the return key into a search key.
				InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
				imm.hideSoftInputFromWindow(editSearch.getWindowToken(), 0);

				mSearchAction.setIcon(getResources().getDrawable(R.drawable.ic_search));

				isSearchOpened = false;

				// Remove the search view and display the title again.
				action.setCustomView(null);
				action.setDisplayShowTitleEnabled(true);

				// Call searchCancelled for any custom actions
				searchCancelled();
			} else {
				// Delete the search query.
				editSearch.setText("");
			}
		} else {
			// Replace the title with a search bar.
			action.setDisplayShowCustomEnabled(true);
			action.setCustomView(R.layout.search_bar);
			action.setDisplayShowTitleEnabled(false);

			editSearch = (EditText) action.getCustomView().findViewById(R.id.editSearch);

			// Execute doSearch() when the search key is pressed.
			editSearch.setOnEditorActionListener(new TextView.OnEditorActionListener() {
				@Override
				public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
					if(actionId == EditorInfo.IME_ACTION_SEARCH) {
						doSearch();
						return true;
					} 
					return false;
				}
			});

			// Call doSearch() every time that the search query is changed.
			editSearch.addTextChangedListener(new TextWatcher() {
				@Override
				public void afterTextChanged(Editable s) {
					doSearch();
				}

				@Override
				public void beforeTextChanged(CharSequence s, int start, int before, int count) {}

				@Override
				public void onTextChanged(CharSequence s, int start, int before, int count) {}
			});
			
			editSearch.requestFocus();

			InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
			imm.showSoftInput(editSearch, InputMethodManager.SHOW_IMPLICIT);

			mSearchAction.setIcon(getResources().getDrawable(R.drawable.ic_close));

			isSearchOpened = true;
		}
	}

	public void doSearch() {
		// To be overridden by subclasses.
	}

	public void searchCancelled() {
		// To be overridden by subclasses
	}

}
